package com.chenfan.magic.interpreter;

import com.chenfan.magic.core.IdcEngineEntry;
import com.chenfan.magic.core.MagicLogPublisher;
import com.chenfan.magic.entity.TTLDetailModel;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.util.Map;

/**
 * javascript动态解释工具类 [必须 JDK1.6+]
 * 注意: 仅支持传统标准 js 语法. 不支持 es 语法.
 * <p>
 * 示例: run("function handler(scope){" + code + "}", paramMap);
 *
 * @author caohui
 */
@Slf4j
@Component
@AllArgsConstructor
public class JavascriptInterpreter implements __IInterpreter {

    public static final String TYPE_CODE = "javascript";
    public static final String ALIAS = "js";

    @Override
    public Object run(Map<String, Object> idcRuntimePool, String code, Map<String, Object> paramMap) {
        TTLDetailModel ttlDetailModel = new TTLDetailModel();
        ttlDetailModel.start();
        Object result = null;
        try {
            ScriptEngineManager manager = new ScriptEngineManager();
            ScriptEngine engine = manager.getEngineByName(TYPE_CODE);
            engine.eval(code);
            if (engine instanceof Invocable) {
                Invocable in = (Invocable) engine;
                result = in.invokeFunction(__IInterpreter.HANDER_NAME, paramMap);
            }
            MagicLogPublisher.publishInterpreterEvent(TYPE_CODE, code, result, paramMap, ttlDetailModel.end().getTtl() + "");
        } catch (Exception e) {
            e.printStackTrace();
            IdcEngineEntry.throwException(idcRuntimePool, null, e);
            MagicLogPublisher.publishInterpreterEvent(TYPE_CODE, code, result, paramMap, ttlDetailModel.end().getTtl() + "", e);
        }
        return result;
    }

    @Override
    public Object run(Map<String, Object> idcRuntimePool, String expression, String defaultValue) {
        return defaultValue;
    }

    /**
     * 测试执行
     *
     * @param args
     */
    public static void main(String[] args) {
        String code = "function handler(scope){\n" +
                "  \n" +
                "  return 'fuck you';\n" +
                "}";
        Map<String, Object> paramMap = Maps.newHashMap();
        String res = new JavascriptInterpreter().run(null, code, paramMap) + "";
        System.out.println(res);
    }
}
